package com.allenkerr.rpc.server;

import com.allenkerr.rpc.common.RpcRequest;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.Map;

/**
 * 处理具体的业务调用。
 * 通过构造时传入的包含“业务接口及实现类”的handlerMap，来调用客户端所请求的业务方法，
 * 并将业务方法返回值封装成response对象写入下一个handler（即编码handler：RpcEncoder）。
 * <p>
 * Created by 小柯(Allen Kerr) on 17.5.23 19:53.
 */
public class RpcHandler extends SimpleChannelInboundHandler<RpcRequest> {

    private static final Logger LOGGER = LoggerFactory.getLogger(RpcHandler.class);

    private final Map<String, Object> handlerMap;

    public RpcHandler(Map<String, Object> handlerMap) {
        this.handlerMap = handlerMap;
    }

    /**
     * 接收消息，处理消息，返回结果
     *
     * @param channelHandlerContext
     * @param rpcRequest
     * @throws Exception
     */
    @Override
    public void channelRead0(ChannelHandlerContext channelHandlerContext, RpcRequest rpcRequest) throws Exception {

    }

    /**
     * 根据request来处理具体的业务调用，调用是通过反射的方式来完成的。
     * 1. 获取request消息，通过返回调用实现类
     * 2. 将结果返回给client
     *
     * @param request
     * @return
     */
    private Object handle(RpcRequest request) throws Exception {
        String className = request.getClassName();
        //获取实现类
        Object serviceBean = handlerMap.get(className);
        //获取要调用的方法名、参数类型、返回值
        String methodName = request.getMethodName();
        Class<?>[] parameterTypes = request.getParameterTypes();
        Object[] parameters = request.getParameters();
        //获取接口
        Class<?> interfaceClass = Class.forName(className);
        //调用实现类对象的指定方法，并返回结果
        Method method = interfaceClass.getMethod(methodName, parameterTypes);
        return method.invoke(serviceBean, parameters);
    }
}
